﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using devtm.Aop.Event;
using System.Linq.Expressions;

namespace devtm.Aop.Linq.Boxs
{

    internal class InterceptorTypeBox : InterceptorBase
    {

        public InterceptorTypeBox(Type type, Expression e)
        {

            this.Type = type;
            // récupère les methodes
            GetMethods(type);

            if (BeforeMethod == null && InterceptMethod == null && AfterMethod == null && CatchMethod == null)
                throw new Exception(type.FullName + "isn't a interceptor object");

            if (BeforeMethod != null && !InterceptEventAttribute.Valid(BeforeMethod))
                throw new Exception(BeforeMethod.ToString() + "");

            if (InterceptMethod != null && !InterceptEventAttribute.Valid(InterceptMethod))
                throw new Exception(InterceptMethod.ToString() + "");

            if (AfterMethod != null && !InterceptEventAttribute.Valid(AfterMethod))
                throw new Exception(AfterMethod.ToString() + "");

            if (CatchMethod != null && !InterceptEventAttribute.Valid(CatchMethod))
                throw new Exception(CatchMethod.ToString() + "");

            if (e == null)            
                Properties = new List<KeyValuePair<string, object>>();
            
            else
            {
                Visitor v = new Visitor();
                v.Visit(e);
                Properties = v.List;
            }

        }

        private void GetMethods(Type type)
        {

            foreach (MethodInfo m in type.GetMethods())
            {

                foreach (InterceptEventAttribute attr in m.GetCustomAttributes(typeof(InterceptEventAttribute), false))
                    switch (attr.InterceptEnumEventType)
                    {
                        case InterceptEnumEventType.BeforeCall:
                            if (BeforeMethod == null)
                                BeforeMethod = m;
                            break;
                        case InterceptEnumEventType.InterceptCall:
                            if (InterceptMethod == null)
                                InterceptMethod = m;
                            break;
                        case InterceptEnumEventType.AfterCall:
                            if (AfterMethod == null)
                                AfterMethod = m;
                            break;
                        case InterceptEnumEventType.Catch:
                            if (CatchMethod == null)
                                CatchMethod = m;
                            break;
                        default:
                            break;
                    }

            }

            if (type.BaseType != null)
            {
                if (BeforeMethod == null || InterceptMethod == null || AfterMethod == null || CatchMethod == null)
                    GetMethods(type.BaseType);
            }
            else
                if (BeforeMethod != null && InterceptMethod != null && AfterMethod != null && CatchMethod != null)
                    return;

        }        

    }
}
